<?php


namespace App\Http\Controllers;

use App\Exceptions\ExceptionApi;
use App\Http\Response\UserResponse;
use App\Models\User;
use App\Services\Config;
use App\Services\Regex;
use App\Services\Sms;
use App\Models\Sms as SmsModel;
use Illuminate\Http\Response;
use Illuminate\Http\Request;
use App\Services\Logger;

class HomeController extends Controller
{

    /**
     * @api {POST} /api/member/getSmscode 发送短信验证码
     * @apiGroup 登录注册
     * @apiParamExample {x-www-form-urlencoded} 参数请求示例:
     * ?phone=15981123456
     * @apiDescription 发送登录短信验证码
     * @apiUse PublicCommonBlock
     * @apiParam {String} phone 用户手机号
     * @apiSuccessExample {json} 成功相应示例
     * {"code":200,"msg":"success","data":null}
     */
    public function getSmsCode(Request $request){
        $mobile = $request->input('phone');
        if(empty($mobile)){
            throw new ExceptionApi('手机号不能为空');
        }
        $smsTpl = Config::get(Config::KEY_SMS_TPL);
        $expire = Config::get(Config::KEY_SMS_EXPIRE_IN_MINUTES); // 10 minutes
        $code = mt_rand(100000, 999999);
        $content = str_replace("{#code#}", $code, $smsTpl);
        $content = str_replace("{#expire#}", $expire, $content);
        $sendTime = date('Y-m-d H:i:s', time() - 5);
        $expiredAt = time() + ($expire * 60);
        $sms = new Sms();
        $sms->send($mobile, $content, $sendTime);

        $smsModel = new SmsModel();
        $smsModel->mobile = $mobile;
        $smsModel->sms_code = $code;
        $smsModel->content = $content;
        $smsModel->expired_at = $expiredAt;
        $smsModel->save();

        return $this->success(null,'发送成功');
    }

    protected function checkSmsCode($mobile, $smsCode){

        // 指定手机号码，输入指定验证码。通过验证。
        $allows = Config::get(Config::KEY_SMS_PASS_MOBILES);
        if(in_array($mobile, $allows) && $smsCode=='135246'){
            return true;
        }

        $sms = SmsModel::query()->where(['mobile'=>$mobile,'sms_code'=>$smsCode,'has_used'=>0])
            ->orderByDesc("expired_at")->first();
        if(!$sms){
            throw new ExceptionApi('短信验证码不正确');
        }
        if($sms['expired_at'] < time()){
            throw new ExceptionApi('短信验证码已过期');
        }
        $sms->has_used = 1;
        $sms->save();
        return true;
    }

    /**
     * @api {POST} /api/member/checkLogin 用户登录|注册
     * @apiGroup 登录注册
     * @apiParamExample {x-www-form-urlencoded} 参数请求示例:
     * ?phone=15981123456&vcode=126859
     * @apiDescription 用户登录接口|注册接口
     * @apiUse PublicCommonBlock
     * @apiParam {String} phone 用户手机号
     * @apiParam {String} vcode 短信验证码
     * @apiSuccess {String} data.nickname 用户昵称
     * @apiSuccess {String} data.token 身份令牌
     * @apiSuccess {String} data.avatar 用户头像
     * @apiSuccessExample {json} 成功相应示例
     * {"code":200,"msg":"success","data":{"code":200,"msg":"success","data":{"id":1,"nickname":"","avatar":"https:\/\/dy.zq.xiantou.com\/uploads\/default.png","token":"tkb.d009f37b422dbf03c27dc89bee4d1ffdb559c2f79088b881147ac4535662931b.1"}}}
     */
    public function smsLogin(Request $request){
        $mobile = $request->input('phone');
        $smsCode = $request->input('vcode');
        $this->checkMobile($mobile);
        if(empty($smsCode)){
            throw new ExceptionApi('短信验证码不能为空');
        }
        if(strlen($smsCode)!=6){
            throw new ExceptionApi('短信验证码必须是6位');
        }

        $this->checkSmsCode($mobile, $smsCode);
        $userInfo = $this->loginOrRegisterByMobile($mobile);
        return $this->success($userInfo,'登录成功!');
    }

    public function checkMobile($mobile):bool{
        if(empty($mobile)){
            throw new ExceptionApi('手机号不能为空');
        }
        if(strlen($mobile)!==11){
            throw new ExceptionApi('手机号必须是11位', 400);
        }
        if(strpos($mobile, "180000000")===0){
            return true;
        }
        if(!Regex::Mobile($mobile)){
            throw new ExceptionApi('手机号不合法', 400);
        }
        return true;
    }

    protected function loginOrRegisterByMobile($mobile){
        $user = User::query()->where(['mobile'=>$mobile])->first();
        $isNew = 0;
        if(!$user){
            $user = User::registerByMobile($mobile);
            $isNew = 1;
        }
        return UserResponse::toArray($user,$isNew);
    }

    /**
     * @api {POST} /api/whq2021/user/freeLogin 手机号一键登录[APP]
     * @apiGroup 登录注册
     * @apiParam {String} token token
     * @apiParam {String} opToken opToken
     * @apiParam {String} operator operator
     * @apiSuccess {integer} code 状态码
     * @apiSuccess {Object} data 响应数据
     * @apiSuccess {integer} ts 时间戳
     * @apiSuccessExample {json} 成功相应示例
     * {"code":200,"msg":"登录成功","data":[],"ts":1616834952}
     * @apiErrorExample {json} 异常响应示例
     * {"code":400,"msg":"请求参数错误","data":[],"ts":1616834952}
     */
    public function freeLogin(Request $request):Response{
        $token = $request->input('token');
        $opToken = $request->input('opToken');
        $operator = $request->input('operator');
        if(empty($token) || empty($opToken) || empty($operator)){
            throw new ExceptionApi('token opToken operator 参数不能为空');
        }
        $mobile = $this->getMobileByMob($token, $opToken, $operator);
        $data = $this->loginOrRegisterByMobile($mobile);
        return $this->success($data,'登录成功');
    }

    protected function getMobileByMob($token, $opToken, $operator){

        function getSign($data, $secret) {
            ksort($data);
            $str = '';
            foreach ($data as $k => $v ) {
                $str .= "$k=$v&";
            }
            $str = substr($str, 0, -1);
            return md5($str.$secret);
        }

        $host = "http://identify.verify.mob.com";
        $url = "{$host}/auth/auth/sdkClientFreeLogin";
        $appkey = Config::get(Config::KEY_MOB_COM_APPID);;
        $appSecret = Config::get(Config::KEY_MOB_COM_SECRET);
        $md5 = Config::get(Config::KEY_MOB_COM_MD5);

        //初始化
        $curl = curl_init();
        //设置抓取的url
        curl_setopt($curl, CURLOPT_URL, $url);
        //设置头文件的信息作为数据流输出
        curl_setopt($curl, CURLOPT_HEADER, 0);
        //设置获取的信息以文件流的形式返回，而不是直接输出。
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
        //设置post方式提交
        curl_setopt($curl, CURLOPT_POST, 0);
        //设置post数据
        $post_data = array(
            "appkey" => $appkey,
            "token" => $token,
            "opToken" => $opToken,
            'operator'=> $operator,
            'timestamp'=> time(), // 1564046825531
        );
        if ($md5 != '') {
            $post_data['md5'] = $md5;
        }
        $post_data['sign'] = getSign($post_data, $appSecret);
        $jsonStr = json_encode($post_data);
        curl_setopt($curl, CURLOPT_POSTFIELDS, $jsonStr);
        curl_setopt($curl, CURLOPT_HTTPHEADER, array(
                'Content-Type: application/json; charset=utf-8',
                'Content-Length: ' . strlen($jsonStr)
            )
        );
        //执行命令
        $data = curl_exec($curl);
        //关闭URL请求
        curl_close($curl);
        $json = json_decode($data);
        if($json->error){
            $msg = '第三方接口返回错误:'.var_export($json->error, true);
            Logger::debug($msg);
            throw new ExceptionApi($msg,400);
        }
        if($json->status!=200){
            throw new ExceptionApi('第三方接口返回错误',400);
        }
        if ($json->status == 200) {
            $d = openssl_decrypt($json->res, "DES-CBC", $appSecret, 0, "00000000");
            //    $des = new CryptDes($appSecret);
            //    $json->res = $des->decrypt($json->res);
            $json->res = json_decode($d, true);
        }
        $res = $json->res;
        $isValid = $res['isValid'];
        $phone = $res['phone'];
        if($isValid==2){
            $msg = '手机号验证失败';
            Logger::debug($msg);
            throw new ExceptionApi($msg,400);
        }
        return $phone;
    }

}
